package com.hzvdvmc.autosale.socket;

import android.support.annotation.NonNull;

import com.hzvdvmc.autosale.constant.CmdEnum;
import com.hzvdvmc.autosale.constant.GlobleCache;
import com.hzvdvmc.autosale.socket.event.CommonEvent;
import com.hzvdvmc.autosale.socket.event.TipEvent;
import com.hzvdvmc.autosale.socket.manager.CmdRequestManager;
import com.hzvdvmc.autosale.socket.manager.CmdResponseManager;
import com.hzvdvmc.autosale.util.LogUtil;
import com.hzvdvmc.autosale.util.StringUtil;
import com.hzvdvmc.autosale.util.TimeUtil;
import com.vilyever.socketclient.SocketClient;
import com.vilyever.socketclient.helper.SocketClientDelegate;
import com.vilyever.socketclient.helper.SocketClientReceivingDelegate;
import com.vilyever.socketclient.helper.SocketClientSendingDelegate;
import com.vilyever.socketclient.helper.SocketPacket;
import com.vilyever.socketclient.helper.SocketPacketHelper;
import com.vilyever.socketclient.helper.SocketResponsePacket;
import com.vilyever.socketclient.util.CharsetUtil;

import org.greenrobot.eventbus.EventBus;

/**
 * Created by william on 2017/12/3.
 */

public class SocketClientManager {
    private SocketClient socketClient;
    private boolean canConnect = true;
    private static final long HEART_BEAT_INTERVAL = 60 * 1000;
    private static SocketClientManager clientManager;

    public static SocketClientManager getInstance() {
        if (clientManager == null) {
            clientManager = new SocketClientManager();
        }
        return clientManager;
    }

    public SocketClient getSocketClient() {
        return socketClient;
    }

    private SocketClientManager() {
        if (socketClient == null) {
            socketClient = new SocketClient();
            String ip = HttpConstants.getScoketIP();
            String port = HttpConstants.getSocketPort();
            socketClient.getAddress().setRemoteIP(ip);
            socketClient.getAddress().setRemotePort(port);
            socketClient.getAddress().setConnectionTimeout(15 * 1000); // 连接超时时长，单位毫秒
            /**
             * 设置自动发送的心跳包信息
             */
            String heart = CmdRequestManager.getInstance().getHeartBeatCommandStr();

            socketClient.getHeartBeatHelper()
                    .setDefaultSendData(StringUtil.hexStringToBytes(heart));
            socketClient.getHeartBeatHelper().setHeartBeatInterval(HEART_BEAT_INTERVAL); // 设置自动发送心跳包的间隔时长，单位毫秒
            socketClient.getHeartBeatHelper().setSendHeartBeatEnabled(true); // 设置允许自动发送心跳包，此值默认为false
            socketClient.setCharsetName(CharsetUtil.UTF_8);
            autoReadToTrailer();
            registerSocket();
        }
    }

    public void disConnect() {
        canConnect = false;
        socketClient.disconnect();
    }


    private void autoReadToTrailer() {
        socketClient.getSocketPacketHelper().setReadStrategy(SocketPacketHelper.ReadStrategy.AutoReadToTrailer);

        //包尾
        socketClient.getSocketPacketHelper().setSendTrailerData(StringUtil.hexStringToBytes("ee"));
        socketClient.getSocketPacketHelper().setReceiveTrailerData(StringUtil.hexStringToBytes("ee"));
        //包头
//        socketClient.getSocketPacketHelper().setSendHeaderData();
//        socketClient.getSocketPacketHelper().setReceiveHeaderData()
    }

    public void connect() {
        String ip = HttpConstants.getScoketIP();
        String port = HttpConstants.getSocketPort();
        socketClient.getAddress().setRemoteIP(ip);
        socketClient.getAddress().setRemotePort(port);
        socketClient.connect();
    }

    public void registerSocket() {
//        / 对应removeSocketClientDelegate
        socketClient.registerSocketClientDelegate(new SocketClientDelegate.SimpleSocketClientDelegate() {
            /**
             * 连接上远程端时的回调
             */
            @Override
            public void onConnected(final SocketClient client) {
                LogUtil.p("--> socket onConnected");
                EventBus.getDefault().post(new TipEvent("连接正常"));
                EventBus.getDefault().post(new CommonEvent(CommonEvent.SOCKET_RECONNET));
            }

            /**
             * 与远程端断开连接时的回调
             */
            @Override
            public void onDisconnected(SocketClient client) {
                // 可在此实现自动重连
                LogUtil.p("--> socket onDisconnected");
                EventBus.getDefault().post(new TipEvent("连接失败"));
                EventBus.getDefault().post(new CommonEvent(CommonEvent.SOCKET_DISCONNET));
                GlobleCache.isSign = false;
                if (canConnect)
                    client.connect();
            }


            /**
             * 接收到数据包时的回调
             */
            @Override
            public void onResponse(final SocketClient client, @NonNull SocketResponsePacket responsePacket) {

                LogUtil.i("--> (socket onResponse)");
                byte[] data = responsePacket.getData(); // 获取接收的byte数组，不为null
                String response = StringUtil.bytesToHexString(data);
                LogUtil.i("<-- receviced response :  " + response);
                try {
                    //取出以48开头的数据，防止错误，比如393939480003.......
                    int index = response.indexOf(CmdEnum.START.getValue());
                    if (index >= 0) {
                        String fullCmd = response.substring(index);
                        CmdResponseManager.getInstance().handleResponse(fullCmd);
                    } else {
                        //没有开始标志：48
                        CmdResponseManager.getInstance().handleResponse(response);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        socketClient.registerSocketClientSendingDelegate(new SocketClientSendingDelegate() {
            /**
             * 数据包开始发送时的回调
             */
            @Override
            public void onSendPacketBegin(SocketClient client, SocketPacket packet) {
                LogUtil.i("--> socket onSendPacketBegin ^-^");
            }

            /**
             * 数据包取消发送时的回调
             * 取消发送回调有以下情况：
             * 1. 手动cancel仍在排队，还未发送过的packet
             * 2. 断开连接时，正在发送的packet和所有在排队的packet都会被取消
             */
            @Override
            public void onSendPacketCancel(SocketClient client, SocketPacket packet) {
                LogUtil.i("--> socket onSendPacketCancel ^-^");
            }

            /**
             * 数据包发送的进度回调
             * progress值为[0.0f, 1.0f]
             * 通常配合分段发送使用
             * 可用于显示文件等大数据的发送进度
             */
            @Override
            public void onSendingPacketInProgress(SocketClient client, SocketPacket packet,
                                                  float progress, int sendedLength) {
                LogUtil.i("--> socket onSendingPacketInProgress : " + progress);
            }

            /**
             * 数据包完成发送时的回调
             */
            @Override
            public void onSendPacketEnd(SocketClient client, SocketPacket packet) {
                LogUtil.i("--> socket onSendPacketEnd ^-^" + TimeUtil.getTime());
            }
        });
    }

    private void registerReciceDelegate() {
        // 对应removeSocketClientReceiveDelegate
        socketClient.registerSocketClientReceiveDelegate(new SocketClientReceivingDelegate() {
            /**
             * 开始接受一个新的数据包时的回调
             */
            @Override
            public void onReceivePacketBegin(SocketClient client, SocketResponsePacket packet) {
                LogUtil.i("socket onReceivePacketBegin <--");
            }

            /**
             * 完成接受一个新的数据包时的回调
             */
            @Override
            public void onReceivePacketEnd(SocketClient client, SocketResponsePacket packet) {
                LogUtil.i("socket onReceivePacketEnd<--");
            }

            /**
             * 取消接受一个新的数据包时的回调
             * 在断开连接时会触发
             */
            @Override
            public void onReceivePacketCancel(SocketClient client, SocketResponsePacket packet) {
                LogUtil.i("socket onReceivePacketCancel<--");
            }

            /**
             * 接受一个新的数据包的进度回调
             * progress值为[0.0f, 1.0f]
             * 仅作用于ReadStrategy为AutoReadByLength的自动读取
             * 因AutoReadByLength可以首先接受到剩下的数据包长度
             */
            @Override
            public void onReceivingPacketInProgress(SocketClient client, SocketResponsePacket packet, float progress, int receivedLength) {
                LogUtil.i("socket onReceivingPacketInProgress<--");
            }
        });
    }
}
